package org.cbyyx.tc.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.cbyyx.tc.common.LoginLocal;
import org.cbyyx.tc.enums.ErrorCode;
import org.cbyyx.tc.constant.UserConstant;
import org.cbyyx.tc.exception.BusinessException;
import org.cbyyx.tc.exception.ThrowUtils;
import org.cbyyx.tc.mapper.UserMapper;
import org.cbyyx.tc.model.dto.userRequest.UserLoginRequest;
import org.cbyyx.tc.model.dto.userRequest.UserRegisterRequest;
import org.cbyyx.tc.model.dto.userRequest.UserUpdateRequest;
import org.cbyyx.tc.model.entity.User;
import org.cbyyx.tc.model.vo.userResponse.UserDetailVO;
import org.cbyyx.tc.model.vo.userResponse.UserVO;
import org.cbyyx.tc.service.UserService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpSession;

/**
* @author cbyyx
* @description 针对表【users】的数据库操作Service实现
* @createDate 2025-04-21 15:35:04
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Value("${password.salt}")
    private String SALT;  // 密码加密盐值，从配置文件中读取

    /**
     * 用户登录方法
     * @param loginRequest 登录请求参数，包含账号和密码
     * @param session HTTP会话对象
     * @return 脱敏后的用户信息
     * @throws BusinessException 如果用户已登录、参数为空或账号密码错误
     */
    @Override
    public UserVO userLogin(UserLoginRequest loginRequest, HttpSession session) {
        if (session.getAttribute(UserConstant.USER_LOGIN_STATE)!=null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"用户已登录");
        }
        String userAccount = loginRequest.getAccount();
        String userPassword = loginRequest.getPassword();
        if (userAccount == null || userPassword == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }
        // 根据用户账号查询用户信息
        String encryptedPassword = DigestUtil.md5Hex(userPassword + SALT);
        User user = this.getOne(new QueryWrapper<User>()
                .eq("account", userAccount)
                .eq("password", encryptedPassword));
        ThrowUtils.throwIf(user == null, ErrorCode.PARAMS_ERROR, "用户名或密码错误");
        // 用户脱敏
        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(user, userVO);
        session.setAttribute(UserConstant.USER_LOGIN_STATE, userVO);
        return userVO;
    }

    /**
     * 用户注册方法
     * @param registerRequest 注册请求参数，包含账号、密码和确认密码
     * @return 注册是否成功
     * @throws BusinessException 如果参数不合法、账号已存在或注册失败
     */
    @Override
    public Boolean userRegister(UserRegisterRequest registerRequest) {
        String userAccount = registerRequest.getAccount();
        String userPassword = registerRequest.getPassword();
        String checkPassword = registerRequest.getCheckPassword();
        ThrowUtils.throwIf(StringUtils.isAnyBlank(userAccount, userPassword, checkPassword), ErrorCode.PARAMS_ERROR, "参数为空");
        ThrowUtils.throwIf(userAccount.length() < 4 || userAccount.length() > 20, ErrorCode.PARAMS_ERROR, "用户账号长度不合法");
        ThrowUtils.throwIf(userPassword.length() < 8 || userPassword.length() > 20, ErrorCode.PARAMS_ERROR, "用户密码长度不合法");
        ThrowUtils.throwIf(!userPassword.equals(checkPassword), ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
        ThrowUtils.throwIf(this.baseMapper.selectCount(new QueryWrapper<User>().eq("account", userAccount)) > 0, ErrorCode.PARAMS_ERROR, "账号已存在");
        String encryptedPassword = DigestUtil.md5Hex(userPassword + SALT);
        User user = new User();
        user.setAccount(userAccount);
        user.setPassword(encryptedPassword);
        if (this.save(user)) {
            return true;
        }
        throw new BusinessException(ErrorCode.SYSTEM_ERROR, "注册失败");
    }

    /**
     * 获取当前登录用户信息
     * @param session HTTP会话对象
     * @return 当前登录用户信息，如果会话过期或数据不一致返回null
     */
    @Override
    public UserVO getCurrentUser(HttpSession session) {
        UserVO loginUser = (UserVO) session.getAttribute(UserConstant.USER_LOGIN_STATE);
        if (loginUser == null) {
            return null;
        }
        //获取登录数据库实时用户信息
        User user = this.getById(loginUser.getId());
        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(user, userVO);
        //比对数据
        if (userVO.equals(loginUser)){
            return userVO;
        }
        //数据不一致
        session.removeAttribute(UserConstant.USER_LOGIN_STATE);
        return null;
    }

    /**
     * 更新用户信息
     * @param updateRequest 更新请求参数，包含用户ID和新密码
     * @return 更新是否成功
     * @throws BusinessException 如果用户不存在或更新失败
     */
    @Override
    public Boolean updateUser(UserUpdateRequest updateRequest) {
        if (this.getById(updateRequest.getId()) == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "用户不存在");
        }
        updateRequest.setPassword(DigestUtil.md5Hex(updateRequest.getPassword() + SALT));
        User user = new User();
        BeanUtil.copyProperties(updateRequest, user);
        if (this.updateById(user)){
            return true;
        }
        throw new BusinessException(ErrorCode.SYSTEM_ERROR, "修改失败");
    }

    /**
     * 获取用户详细信息
     * @param id 用户ID
     * @return 用户详细信息
     * @throws BusinessException 如果ID参数不合法
     */
    @Override
    public UserDetailVO getUser(Long id) {
        ThrowUtils.throwIf(id == null || id <= 0, ErrorCode.PARAMS_ERROR);
        User user = this.getById(id);
        UserDetailVO userDetailVO = new UserDetailVO();
        BeanUtil.copyProperties(user, userDetailVO);
        return userDetailVO;
    }

    @Override
    public Boolean addBalance(Long amount) {
        UserVO loginUser = LoginLocal.getLoginUser();
        return this.lambdaUpdate()
                .eq(User::getId, loginUser.getId())
                .setSql("balance = balance + " + amount)
                .update();
    }
}




